package com.ants.boot.system.service.impl;

import com.ants.boot.core.enums.DataStatusEnum;
import com.ants.boot.core.enums.MenuTypeEnum;
import com.ants.boot.model.BaseModel;
import com.ants.boot.system.dao.SysMenuMapper;
import com.ants.boot.system.domain.SysMenu;
import com.ants.boot.system.dto.sysmenu.AddMenuDto;
import com.ants.boot.system.dto.sysmenu.DelMenuDto;
import com.ants.boot.system.dto.sysmenu.QueryMenuDto;
import com.ants.boot.system.dto.sysmenu.UpdateMenuDto;
import com.ants.boot.system.service.SysMenuService;
import com.ants.boot.system.service.SysRoleMenuService;
import com.ants.boot.system.vo.sysmenu.MenuTreeVo;
import com.ants.boot.system.vo.sysmenu.MetaVo;
import com.ants.boot.system.vo.sysmenu.SelectTreeVo;
import com.ants.boot.utils.Constants;
import com.ants.boot.utils.TreeNodeUtils;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * @author 蚂蚁会花呗
 * @date 2022/2/24 15:09
 */
@Service
public class SysMenuServiceImpl extends ServiceImpl<SysMenuMapper, SysMenu> implements SysMenuService {

    @Autowired
    private SysMenuMapper sysMenuMapper;

    @Autowired
    private SysRoleMenuService sysRoleMenuService;

    @Override
    public List<SysMenu> findMenuPermsByUserId(Integer userId) {
        return sysMenuMapper.findMenuPermsByUserId(userId);
    }

    @Override
    public List<SysMenu> findMenuByUserId(Integer userId) {
        List<SysMenu>  menus = sysMenuMapper.findMenuByUserId(userId);
        return buildTreeMenu(menus);
    }

    @Override
    public List<MenuTreeVo> buildRouterVoMenus(List<SysMenu> menus) {
        List<MenuTreeVo> routers = new LinkedList<MenuTreeVo>();
        for (SysMenu menu : menus){
            MenuTreeVo router = new MenuTreeVo();
            router.setHidden("1".equals(menu.getVisible()));
            router.setName(getRouteName(menu));
            router.setPath(getRouterPath(menu));
            router.setComponent(getComponent(menu));
            router.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon(), 1 == menu.getIsCache()));
            List<SysMenu> cMenus = menu.getChildren();
            if (!cMenus.isEmpty() && MenuTypeEnum.CATALOGUE.getValue().equals(menu.getMenuType())) {
                router.setAlwaysShow(true);
                router.setRedirect("noRedirect");
                router.setChildren(buildRouterVoMenus(cMenus));
            }
            routers.add(router);
        }
        return routers;
    }

    @Override
    public List<SysMenu> listAllMenu() {
        QueryWrapper<SysMenu> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda()
                .eq(BaseModel::getStatus, DataStatusEnum.NORMAL_STATUS.getValue())
                .orderByAsc(SysMenu::getOrderNum);
        return this.list(queryWrapper);
    }

    @Override
    public List<SelectTreeVo> selectTreeMenu() {
        List<SelectTreeVo> result = new ArrayList<>();
        List<SysMenu> listAll = this.listAllMenu();
        if (!listAll.isEmpty()){
            //1.先构建成树形列表
            List<SysMenu> tree = buildTreeMenu(listAll);
            //2.构建符合下拉框的树形结构
            result = buildSelectTreeMenu(tree);
        }
        return result;
    }

    @Override
    public List<Integer> roleCheckMenuIds(Integer roleId) {
        List<Integer> ids =  sysRoleMenuService.listMenuIdsByRoleId(roleId);
        return ids;
    }

    @Override
    public List<SysMenu> listMenuTree(QueryMenuDto dto) {
        QueryWrapper<SysMenu> queryWrapper = new QueryWrapper<>();
        if (StringUtils.isNotBlank(dto.getMenuName())){
            queryWrapper.lambda()
                    .like(SysMenu::getMenuName,dto.getMenuName());
        }
        if (StringUtils.isNotBlank(dto.getStatus())){
            queryWrapper.and(wrapper ->wrapper.lambda().eq(SysMenu::getStatus,dto.getStatus()));
        }
        List<SysMenu> list = this.list(queryWrapper);
        Collections.sort(list, Comparator.comparing(SysMenu::getOrderNum));
        List<SysMenu> tree = buildTreeMenu(list);
        return tree;
    }

    @Override
    public boolean addMenu(AddMenuDto dto) {
        SysMenu sysMenu = new SysMenu();
        BeanUtils.copyProperties(dto,sysMenu);
        if (StringUtils.isBlank(dto.getComponent())){
            sysMenu.setComponent("");
        }
        if (StringUtils.isBlank(dto.getPerms())){
            sysMenu.setPerms("");
        }
        return this.save(sysMenu);
    }

    @Override
    public boolean updateMenu(UpdateMenuDto dto) {
        SysMenu sysMenu = new SysMenu();
        BeanUtils.copyProperties(dto,sysMenu);
        return this.saveOrUpdate(sysMenu);
    }

    @Override
    public boolean delMenu(DelMenuDto dto) {
        SysMenu sysMenu =  this.getById(dto.getId());
        if (!sysMenu.getMenuType().equals(MenuTypeEnum.BUTTON)){
            if (sysMenu.getMenuType().equals(MenuTypeEnum.MENU)){
                removeByPid(sysMenu.getId());
            }
        }
        return this.removeById(dto.getId());
    }


    /**
     * 获取路由名称 返回path 的
     *
     * @param menu 菜单信息
     * @return 路由名称
     */
    public String getRouteName(SysMenu menu) {
        String routerName = StringUtils.capitalize(menu.getPath());
        return routerName;
    }

    /**
     * 获取路由地址
     *
     * @param menu 菜单信息
     * @return 路由地址
     */
    public String getRouterPath(SysMenu menu) {
        String routerPath = menu.getPath();
        // 非外链并且是一级目录（类型为目录）
        if (0 == menu.getPid() && MenuTypeEnum.CATALOGUE.getValue().equals(menu.getMenuType())) {
            routerPath = "/" + menu.getPath();
        }
        return routerPath;
    }


    /**
     * 获取组件信息
     *
     * @param menu 菜单信息
     * @return 组件信息
     */
    public String getComponent(SysMenu menu) {
        String component = Constants.LAYOUT;
        if (StringUtils.isNotEmpty(menu.getComponent())) {
            component = menu.getComponent();
        } else if (StringUtils.isEmpty(menu.getComponent()) && isParentView(menu)) {
            component = Constants.PARENT_VIEW;
        }
        return component;
    }


    /**
     * 是否为parent_view组件
     *
     * @param menu 菜单信息
     * @return 结果
     */
    public boolean isParentView(SysMenu menu) {
        return menu.getPid() != 0 && MenuTypeEnum.CATALOGUE.getValue().equals(menu.getMenuType());
    }

    /**
     * 构建树形结构的菜单
     * @param list
     * @return
     */
    private List<SysMenu> buildTreeMenu(List<SysMenu> list){
        List<?> tree = new TreeNodeUtils(list).buildTree("id","pid","0","children");
        return (List<SysMenu>) tree;
    }

    /**
     * 构建符合前端的树形下拉框
     * @param list
     * @return
     */
    public List<SelectTreeVo> buildSelectTreeMenu(List<SysMenu> list){
        List<SelectTreeVo> tree = new LinkedList<SelectTreeVo>();
        for (SysMenu menu : list){
            SelectTreeVo vo = new SelectTreeVo();
            vo.setId(menu.getId());
            vo.setLabel(menu.getMenuName());
            List<SysMenu> cMenus = menu.getChildren();
            if (!cMenus.isEmpty()) {
                vo.setChildren(buildSelectTreeMenu(cMenus));
            }
            tree.add(vo);
        }
        return tree;
    }


    /**
     * 根据pid删除
     * @param pid
     */
    private void removeByPid(Integer pid){
        QueryWrapper<SysMenu> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda()
                .eq(SysMenu::getPid,pid);
        this.remove(queryWrapper);
    }


}
